home *** CD-ROM | disk | FTP | other *** search
/ Amiga Developer CD 2.1 / Amiga Developer CD v2.1.iso / CDTV / cdxltools1-11 / Code / Example.c next >
Encoding:
C/C++ Source or Header  |  1992-03-02  |  24.3 KB  |  1,073 lines

  1. /************************************************************************
  2. **********                                                     **********
  3. **********                     CDXL Tools                      **********
  4. **********                     ----------                   **********
  5. **********                                                     **********
  6. **********           Copyright (C) Pantaray Inc. 1991          **********
  7. **********               Ukiah, CA  707-462-4878               **********
  8. **********                All Rights Reserved.                 **********
  9. **********                                                     **********
  10. *************************************************************************
  11. ***
  12. ***  MODULE:
  13. ***
  14. ***    Example.c
  15. ***
  16. ***  PURPOSE:
  17. ***
  18. ***    Show example of simple CDXL player
  19. ***
  20. ***  HISTORY:
  21. ***
  22. ***    1.00 1a22 Ken Yeast    First Release.
  23. ***    1.01 1b12 Ken Yeast    Added back in audio support
  24. ***    1.02 1c17 Ken Yeast    Use Size for frame size
  25. ***                CDTV_NAME
  26. ***                Used Intuition to center screen in a more compatible
  27. ***                way.
  28. ***                Forgot to CloseDevice and DeletePort on CDTVIOReq!
  29. ***    1.03 1c23 Ken Yeast    Changed to ask Audio.device for channels
  30. ***                Also to double buffer the audio
  31. ***                Init/QuitCDTV
  32. ***                Init/QuitViewInfo
  33. ***                StartAudio
  34. ***    1.04 1c27 Ken Yeast    OK, LoadRGB4 is too slow.  Changed to create view/etc.
  35. ***                and then copy and use the resulting copper lists.
  36. ***                CopyCopper
  37. ***                CopyColors
  38. ***    1.05 2102 Ken Yeast    Cleanup and preload two frames
  39. ***    1.06 2115 Ken Yeast    Removed DOSBase
  40. ***    1.07 2120 Ken Yeast    Example does little stdio and is mostly using Wait,
  41. ***                so we can just check for the SIGBREAKF_CTRL_C signal.
  42. ***                Will triple buffer if audio is present
  43. ***                Some cleanup
  44. ***    1.08 2120 Ken Yeast    Second Release
  45. ***    1.09 2128 Ken Yeast    Can be played multiple times or forever
  46. ***                StopAudio
  47. ***         2218 Ken Yeast    Checked out with some XL streams on CDTV
  48. ***                Stop one frame early
  49. ***    1.10 2303 Ken Yeast    Official Second Release
  50. ***
  51. ************************************************************************/
  52.  
  53.  
  54. #define    VER 1
  55. #define    REV 10
  56.  
  57.  
  58. #include <stdio.h>
  59. #include <ctype.h>
  60. #include <string.h>
  61. #include <stdlib.h>
  62.  
  63. #include <exec/types.h>
  64. #include <exec/memory.h>
  65. #include <exec/lists.h>
  66. #include <exec/interrupts.h>
  67. #include <exec/io.h>
  68. #include <devices/audio.h>
  69. #include <libraries/dos.h>
  70. #include <cdtv/cdtv.h>
  71. #include <graphics/gfx.h>
  72. #include <graphics/gfxbase.h>
  73. #include <graphics/view.h>
  74. #include <graphics/copper.h>
  75. #include <hardware/custom.h>
  76. #include <hardware/dmabits.h>
  77. #include <hardware/intbits.h>
  78.  
  79. #include <proto/exec.h>
  80. #include <proto/dos.h>
  81. #include <proto/graphics.h>
  82. #include <proto/intuition.h>
  83.  
  84. #include "pan.h"
  85.  
  86.  
  87. /***********************************************************************
  88. ***
  89. ***  Definitions
  90. ***
  91. ************************************************************************/
  92.  
  93. typedef        short            SHORT;
  94. typedef        char *            CSTR;
  95.  
  96. #define        INTDIV( a, b )        ( ( (a) + ( (b) / 2 ) ) / (b) )
  97.  
  98. #define        CDTV_SECTOR_SIZE    2048
  99. #define        CDXL_SPEED_BPS        ( 75 * CDTV_SECTOR_SIZE )
  100.  
  101. // Buffering
  102. #define        MAX_NODES        3
  103. #define        NEXT_FRAME( n, m )    ( ( (n) == ( m - 1 ) ) ? 0 : ( (n) + 1 ) )
  104.  
  105. // Copper lists
  106. #define        COPPER_BUFFER_SIZE    2048
  107. #define        COPPER_END        0xfffffffe
  108. #define        COPPER_MOVE_COLOR0    ( 0x0180 )
  109.  
  110. // Audio has different periods on NTSC vs PAL
  111. #define        NTSC_FREQ        3579545
  112. #define        PAL_FREQ        3546895
  113.  
  114. // Hardware Interrupt control
  115. #define        ENABLE_INTR( f )    CustomPtr->intena = (INTF_SETCLR | (f) )
  116. #define        DISABLE_INTR( f )    CustomPtr->intena = (f)
  117. #define        CLEAR_INTR( f )        CustomPtr->intreq = (f)
  118. #define        ENABLE_DMA( f )        CustomPtr->dmacon = (DMAF_SETCLR | DMAF_MASTER | (f) )
  119. #define        DISABLE_DMA( f )    CustomPtr->dmacon = (f)
  120.  
  121.  
  122. /***********************************************************************
  123. ***
  124. ***  Function Prototypes
  125. ***
  126. ***********************************************************************/
  127.  
  128. void    main( LONG, CSTR * );
  129. void    __interrupt __saveds AudioIntrCode( void );
  130. void    __interrupt __saveds __asm CDXLIntrCode( register __a2 struct CDXL * );
  131. void    CDXLPlay( ULONG, ULONG, ULONG, LONG );
  132. void    CopyColors( UWORD *, UWORD *, SHORT );
  133. UWORD    *CopyCopper( UWORD * );
  134. void    Error( CSTR );
  135. void    Init( void );
  136. void    InitAudio( void );
  137. void    InitCDTV( void );
  138. void    InitCDXL( void );
  139. void    InitViewInfo( void );
  140. void    Quit( LONG );
  141. void    QuitAudio( void );
  142. void    QuitCDTV( void );
  143. void    QuitCDXL( void );
  144. void    QuitViewInfo( void );
  145. void    SetViewInfo( LONG, PAN *, ULONG );
  146. void    StartAudio( void );
  147. void    StopAudio( void );
  148.  
  149.  
  150. /***********************************************************************
  151. ***
  152. ***  Global Variables
  153. ***
  154. ***********************************************************************/
  155.  
  156. struct    GfxBase *GfxBase        = NULL;
  157. struct    IntuitionBase *IntuitionBase    = NULL;
  158.  
  159. // Program
  160. CSTR    Program                = NULL;
  161. struct    Task *OurTask            = NULL;
  162.  
  163. // cdtv.device
  164. struct    IOStdReq *CDTVIOReq        = NULL;
  165. struct    MsgPort *CDTVIOPort        = NULL;
  166.  
  167. // CDXL
  168. SHORT    MaxNodes            = MAX_NODES;
  169. struct    MinList    CDXLList;
  170. struct    CDXL    CDXLNodes[ MAX_NODES ];
  171.  
  172. // Files
  173. CSTR    CDXLFile            = NULL;
  174. ULONG    CDXLSector            = 0;
  175. ULONG    CDXLNumSectors            = 0;
  176. ULONG    CDXLNumFrames            = 0;
  177.  
  178. // CDXL Frame
  179. PAN    FirstPan;
  180. UBYTE    *FrameBuffer[ MAX_NODES ];
  181. UWORD    *FrameCMap[ MAX_NODES ];
  182. UWORD    *FrameAudio[ MAX_NODES ];
  183. ULONG    Count                = 0;
  184.  
  185. // Display
  186. struct    View     CDXLView[ MAX_NODES ];
  187. struct    ViewPort CDXLVP[ MAX_NODES ];
  188. struct    BitMap     CDXLBM[ MAX_NODES ];
  189. struct    RasInfo     CDXLRI[ MAX_NODES ];
  190. UWORD    *Copper[ MAX_NODES ];
  191. UWORD    *Color[ MAX_NODES ];
  192.  
  193. // Signals
  194. LONG    SwitchSignal            = -1;
  195. LONG    SwitchSignalBit            = -1;
  196.  
  197. // Misc
  198. struct    Custom *CustomPtr        = (struct Custom *) 0x00dff000;
  199.  
  200. // Audio
  201. SHORT    AudioHandlerInUse         = FALSE;
  202. struct    Interrupt AudioInterrupt    = { NULL, NULL, NT_INTERRUPT, 5, "AI_Example",
  203.                         NULL, (void (*)( void )) &AudioIntrCode };
  204. struct    Interrupt *OldAudioVector    = NULL;
  205. struct    IOAudio AudioMain;
  206. struct    MsgPort *AudioMainPort        = NULL;
  207. ULONG    AudioFrame            = 0;
  208.  
  209.  
  210. /***********************************************************************
  211. ***
  212. ***  main
  213. ***
  214. ***    main entry point
  215. ***
  216. ***********************************************************************/
  217.  
  218. void main(
  219.     LONG argc,
  220.     CSTR argv[]
  221.     )
  222.     {
  223.     LONG NumPlays = 1;
  224.  
  225.     printf( "CDXL Example Player %d.%02d by Pantaray, Inc. Ukiah CA\n", VER, REV );
  226.  
  227.     // workbench
  228.     if ( argc == 0 )
  229.         exit( RETURN_FAIL );
  230.  
  231.     // Usage
  232.     if ( argc < 2 )
  233.         {
  234.         printf( "USAGE: Example CDXLFile <# Plays, -1 forever>\n" );
  235.         exit( RETURN_FAIL );
  236.         }
  237.  
  238.     // program name as executed, CDXL file to animate
  239.     Program     = argv[ 0 ];
  240.     CDXLFile = argv[ 1 ];
  241.  
  242.     if ( argc > 2 )
  243.         {
  244.         NumPlays = atol( argv[ 2 ] );
  245.         if ( NumPlays < 1 )
  246.             NumPlays = -1;
  247.         }
  248.  
  249.     Init();
  250.  
  251.     CDXLPlay( CDXLSector, CDXLNumSectors, CDXLNumFrames, NumPlays );
  252.  
  253.     Quit( RETURN_OK );
  254.     }
  255.  
  256.  
  257. /***********************************************************************
  258. ***
  259. ***  AudioIntrCode
  260. ***
  261. ************************************************************************/
  262.  
  263. void __interrupt __saveds AudioIntrCode(
  264.     void
  265.     )
  266.     {
  267.     CLEAR_INTR( INTF_AUD0 );
  268.  
  269.     AudioFrame = NEXT_FRAME( AudioFrame, MaxNodes );
  270.     CustomPtr->aud[ 0 ].ac_ptr = CustomPtr->aud[ 1 ].ac_ptr = FrameAudio[ AudioFrame ];
  271.     }
  272.  
  273.  
  274. /***********************************************************************
  275. ***
  276. ***  CDXLIntrCode
  277. ***
  278. ************************************************************************/
  279.  
  280. void __interrupt __saveds __asm CDXLIntrCode(
  281.     register __a2 struct CDXL *NodeCompleted
  282.     )
  283.     {
  284.     Count++;
  285.     Signal( OurTask, SwitchSignal );
  286.     }
  287.  
  288.  
  289. /***********************************************************************
  290. ***
  291. ***  CDXLPlay
  292. ***
  293. ***    Note:
  294. ***    This example assumes a CDXL file with all frames equal.
  295. ***    Video with audio uses triple buffering, vs. double buffering.
  296. ***    Play until (NumFrames-1)
  297. ***
  298. ************************************************************************/
  299.  
  300. void CDXLPlay(
  301.     ULONG Sector,
  302.     ULONG NumSectors,
  303.     ULONG NumFrames,
  304.     LONG NumPlays
  305.     )
  306.     {
  307.     ULONG BufferNum;
  308.     LONG PortSignal;
  309.     LONG SignalMask;
  310.     LONG SignalIn;
  311.     SHORT FramesToBuffer;
  312.     SHORT NumColors        = ( CMAP_SIZE( &FirstPan ) >> 1 );
  313.     BOOL ForEver        = ( NumPlays == -1 );
  314.     BOOL AudioStarted;
  315.     BOOL StopProgram    = FALSE;
  316.  
  317.     do
  318.         {
  319.         // CDXL counters and flags
  320.         Count        = 0;
  321.         BufferNum    = 0;
  322.         AudioFrame    = 0;
  323.         AudioStarted    = FALSE;
  324.         FramesToBuffer    = ( ( MaxNodes > 2 ) ? ( MaxNodes - 2 ) : 0 );
  325.  
  326.         // Signal from device, make sure it is clear.
  327.         PortSignal    = ( 1 << CDTVIOPort->mp_SigBit );
  328.         SetSignal( 0, PortSignal );
  329.         SignalMask    = ( SwitchSignal | PortSignal | SIGBREAKF_CTRL_C );
  330.  
  331.         // Start CDXL with cdtv.device
  332.         CDTVIOReq->io_Command = CD_READXL;
  333.         CDTVIOReq->io_Offset  = Sector;
  334.         CDTVIOReq->io_Length  = NumSectors;
  335.         CDTVIOReq->io_Data    = (APTR) CDXLList.mlh_Head;
  336.         SendIO( (struct IORequest *) CDTVIOReq );
  337.  
  338.         while ( Count < ( NumFrames - 1 ) )
  339.             {
  340.             SignalIn = Wait( SignalMask );
  341.             if ( SignalIn & SIGBREAKF_CTRL_C )
  342.                 {
  343.                 StopProgram = TRUE;
  344.                 break;
  345.                 }
  346.  
  347.             if ( SignalIn & PortSignal )
  348.                 break;
  349.  
  350.             // May need to buffer some frames
  351.             if ( FramesToBuffer > 0 )
  352.                 {
  353.                 FramesToBuffer--;
  354.                 continue;
  355.                 }
  356.  
  357.             // Start audio only once
  358.             if ( ( ! AudioStarted ) && FirstPan.AudioSize )
  359.                 {
  360.                 AudioStarted = TRUE;
  361.                 StartAudio();
  362.                 }
  363.  
  364.             // Insert colors and display frame
  365.             CopyColors( FrameCMap[ BufferNum ], Color[ BufferNum ], NumColors );
  366.             GfxBase->LOFlist = Copper[ BufferNum ];
  367.  
  368.             // Switch to other buffer
  369.             BufferNum = NEXT_FRAME( BufferNum, MaxNodes );
  370.             }
  371.  
  372.         // May need to turn off audio
  373.         if ( AudioStarted )
  374.             {
  375.             StopAudio();
  376.             AudioStarted = FALSE;
  377.             }
  378.  
  379.         // This correctly terminates a CDXL
  380.         AbortIO( (struct IORequest *) CDTVIOReq );
  381.         WaitIO(  (struct IORequest *) CDTVIOReq );
  382.  
  383.         // Then a SEEK is required to force the drive to stop (sometimes necessary)
  384.         CDTVIOReq->io_Command = CDTV_SEEK;
  385.         CDTVIOReq->io_Offset  = 0;
  386.         CDTVIOReq->io_Length  = 0;
  387.         CDTVIOReq->io_Data    = NULL;
  388.         (void) DoIO( (struct IORequest *) CDTVIOReq );
  389.  
  390.         if ( StopProgram )
  391.             break;
  392.  
  393.         } while ( ForEver || ( --NumPlays > 0 ) );
  394.     }
  395.  
  396.  
  397. /***********************************************************************
  398. ***
  399. ***  chkabort
  400. ***
  401. ***    Remove Lattice's CTRL-C
  402. ***
  403. ************************************************************************/
  404.  
  405. void chkabort(
  406.     void
  407.     )
  408.     {
  409.     }
  410.  
  411.  
  412. /***********************************************************************
  413. ***
  414. ***  CopyColors
  415. ***
  416. ************************************************************************/
  417.  
  418. void CopyColors(
  419.     UWORD *CMap,
  420.     UWORD *CopperCMap,
  421.     SHORT NumColors
  422.     )
  423.     {
  424.     do
  425.         {
  426.         // Skip over Load instruction
  427.         CopperCMap++;
  428.  
  429.         // Copy color
  430.         *CopperCMap++ = *CMap++;
  431.         } while ( --NumColors );
  432.     }
  433.  
  434.  
  435. /***********************************************************************
  436. ***
  437. ***  CopyCopper
  438. ***
  439. ************************************************************************/
  440.  
  441. UWORD *CopyCopper(
  442.     UWORD *Copper
  443.     )
  444.     {
  445.     UWORD *Colors     = ( GfxBase->LOFlist + 3 );
  446.     ULONG *Ptr     = (ULONG *) GfxBase->LOFlist;
  447.     ULONG *CopperPtr = (ULONG *) Copper;
  448.     SHORT i;
  449.  
  450.     for ( i = 0; i < ( COPPER_BUFFER_SIZE >> 2 ); i++ )
  451.         {
  452.         *CopperPtr = *Ptr;
  453.  
  454.         // Look for start of color table
  455.         if ( ( *( (UWORD *) Ptr ) & 0x1f ) == COPPER_MOVE_COLOR0 )
  456.             Colors = (UWORD *) CopperPtr;
  457.  
  458.         // Check for end of copper
  459.         if ( *Ptr == COPPER_END )
  460.             break;
  461.  
  462.         Ptr++;
  463.         CopperPtr++;
  464.         }
  465.  
  466.     return( Colors );
  467.     }
  468.  
  469.  
  470. /***********************************************************************
  471. ***
  472. ***  CXBRK
  473. ***
  474. ***    Remove Lattice's CTRL-C
  475. ***
  476. ************************************************************************/
  477.  
  478. void CXBRK(
  479.     void
  480.     )
  481.     {
  482.     }
  483.  
  484.  
  485. /***********************************************************************
  486. ***
  487. ***  Error
  488. ***
  489. ***********************************************************************/
  490.  
  491. void Error(
  492.     CSTR str
  493.     )
  494.     {
  495.     puts( str );
  496.     Quit( RETURN_FAIL );
  497.     }
  498.  
  499.  
  500. /***********************************************************************
  501. ***
  502. ***  Init
  503. ***
  504. ***********************************************************************/
  505.  
  506. void Init(
  507.     void
  508.     )
  509.     {
  510.     if ( ! ( GfxBase = (struct GfxBase *) OpenLibrary( "graphics.library", 0 ) ) )
  511.         Error( "NOT an Amiga System" );
  512.  
  513.     if ( ! ( IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", 0 ) ) )
  514.         Error( "Intuition not available" );
  515.  
  516.     // Setup for communications with CDTV
  517.     InitCDTV();
  518.  
  519.     // Setup CDXL variables and read first pan for sizes
  520.     InitCDXL();
  521.  
  522.     // Audio
  523.     InitAudio();
  524.  
  525.     // setup for view
  526.     InitViewInfo();
  527.     }
  528.  
  529.  
  530. /***********************************************************************
  531. ***
  532. ***  InitAudio
  533. ***
  534. ***    Four audio requests because we are double buffering left & right.
  535. ***    Ask for left and right
  536. ***
  537. ***    left,    right,    right,    left
  538. ***    1,    2,    4,    8
  539. ***
  540. ************************************************************************/
  541.  
  542. void InitAudio(
  543.     void
  544.     )
  545.     {
  546.     static UBYTE AskChannel[] =
  547.         {
  548.         ( 1 + 2 ),
  549.         ( 1 + 4 ),
  550.         ( 4 + 8 ),
  551.         ( 2 + 8 )
  552.         };
  553.     ULONG Frequency;
  554.     LONG AudioRate;
  555.     UWORD AudioPeriod;
  556.  
  557.     // May not be necessary
  558.     if ( FirstPan.AudioSize == 0 )
  559.         return;
  560.  
  561.     // Setup request for initial channel allocation
  562.     if ( ! ( AudioMainPort = CreatePort( 0, 0 ) ) )
  563.         Error( "Could not create port for audio" );
  564.  
  565.     AudioMain.ioa_Request.io_Message.mn_ReplyPort    = AudioMainPort;
  566.     AudioMain.ioa_Request.io_Message.mn_Node.ln_Pri    = 127;
  567.     AudioMain.ioa_Request.io_Command        = ADCMD_ALLOCATE;
  568.     AudioMain.ioa_Request.io_Flags            = ADIOF_NOWAIT;
  569.     AudioMain.ioa_AllocKey                = 0;
  570.     AudioMain.ioa_Data                = AskChannel;
  571.     AudioMain.ioa_Length                = sizeof( AskChannel );
  572.  
  573.     if ( OpenDevice( "audio.device", 0, (struct IORequest *) &AudioMain, 0 ) )
  574.         Error( "Cannot obtain audio channels" );
  575.  
  576.     // Setup audio interrupt
  577.     CLEAR_INTR( INTF_AUD0 );
  578.     OldAudioVector      = SetIntVector( INTB_AUD0, &AudioInterrupt );
  579.     AudioHandlerInUse = TRUE;
  580.  
  581.     // Calculate period
  582.     Frequency      = ( ( GfxBase->DisplayFlags & PAL ) ? PAL_FREQ : NTSC_FREQ );
  583.     AudioRate      = INTDIV( ( CDXL_SPEED_BPS * FirstPan.AudioSize ), FirstPan.Size );
  584.     AudioPeriod      = (UWORD) INTDIV( Frequency, AudioRate );
  585.  
  586.     // Set hardware
  587.     CustomPtr->aud[ 0 ].ac_vol = CustomPtr->aud[ 1 ].ac_vol = 60;
  588.     CustomPtr->aud[ 0 ].ac_per = CustomPtr->aud[ 1 ].ac_per = AudioPeriod;
  589.     CustomPtr->aud[ 0 ].ac_ptr = CustomPtr->aud[ 1 ].ac_ptr = FrameAudio[ 0 ];
  590.     CustomPtr->aud[ 0 ].ac_len = CustomPtr->aud[ 1 ].ac_len = ( FirstPan.AudioSize / sizeof( UWORD) );
  591.     }
  592.  
  593.  
  594. /***********************************************************************
  595. ***
  596. ***  InitCDTV
  597. ***
  598. ************************************************************************/
  599.  
  600. void InitCDTV(
  601.     void
  602.     )
  603.     {
  604.     if ( ! ( CDTVIOPort = CreatePort( 0, 0 ) ) )
  605.         Error( "Cannot create a CDTV port" );
  606.  
  607.     if ( ! ( CDTVIOReq = CreateStdIO( CDTVIOPort ) ) )
  608.         Error( "Cannot attach CDTV StdIO" );
  609.  
  610.     if ( OpenDevice( CDTV_NAME, 0, (struct IORequest *) CDTVIOReq, 0 ) )
  611.         Error( "CDTV Device will not open" );
  612.     }
  613.  
  614.  
  615. /***********************************************************************
  616. ***
  617. ***  InitCDXL
  618. ***
  619. ***    - Get the sector for CDXL (where it starts)
  620. ***    - Get size (# of sectors, # of frames)
  621. ***    - Read first pan for sizes
  622. ***    - Double buffer for video, triple buffer if using audio as well
  623. ***    - Allocate frame buffers and prepare CDXL list
  624. ***    - Signal for frame changing
  625. ***
  626. ************************************************************************/
  627.  
  628. void InitCDXL(
  629.     void
  630.     )
  631.     {
  632.     struct    FileLock *FileLock;
  633.     struct    FileInfoBlock *fib;
  634.     ULONG    Size;
  635.     LONG    fsLock;
  636.     LONG    File;
  637.     UBYTE    fibbuf[ ( sizeof( struct FileInfoBlock ) + 3 ) ];
  638.     SHORT    i;
  639.  
  640.     if ( ! ( fsLock = Lock( CDXLFile, ACCESS_READ ) ) )
  641.         Error( "CDXL file not available" );
  642.  
  643.     FileLock = (struct FileLock *) BADDR( fsLock );
  644.  
  645.     // Pluck the sector right out of public part of the structure
  646.     CDXLSector = FileLock->fl_Key;
  647.  
  648.     // Get size of file.
  649.     // (Force longword alignment of fib pointer.)
  650.     fib = (struct FileInfoBlock *) ( (LONG) ( fibbuf + 3 ) & ~3L );
  651.     Examine( fsLock, fib );
  652.     Size = fib->fib_Size;
  653.  
  654.     UnLock( fsLock );
  655.  
  656.     // Get the first PAN
  657.     if ( ! ( File = Open( CDXLFile, MODE_OLDFILE ) ) )
  658.         Error( "CDXL file not available" );
  659.  
  660.     if ( Read( File, &FirstPan, PAN_SIZE ) != PAN_SIZE )
  661.         {
  662.         Close( File );
  663.         Error( "Not a CDXL file" );
  664.         }
  665.  
  666.     Close( File );
  667.  
  668.     CDXLNumSectors = ( Size / CDTV_SECTOR_SIZE );
  669.     CDXLNumFrames  = ( Size / FirstPan.Size );
  670.  
  671.     // Video with audio need triple buffering, video just double
  672.     MaxNodes = ( ( FirstPan.AudioSize ) ? 3 : 2 );
  673.  
  674.     // Now that we know size of frame, allocate our two buffers, set ptrs,
  675.     // and prepare CDXL List (static)
  676.     NewList( (struct List *) &CDXLList );
  677.  
  678.     for ( i = 0; i < MaxNodes; i++ )
  679.         {
  680.         if ( ! ( FrameBuffer[ i ] = AllocMem( FirstPan.Size, ( MEMF_CHIP | MEMF_CLEAR ) ) ) )
  681.             Error( "Not enough memory for CDXL frame buffers" );
  682.  
  683.         FrameCMap[ i ]    = (UWORD *) ( FrameBuffer[ i ] + PAN_SIZE );
  684.         FrameAudio[ i ]    = (UWORD *) ( FrameBuffer[ i ] + FRAME_SIZE( &FirstPan ) - FirstPan.AudioSize );
  685.  
  686.         AddTail( (struct List *) &CDXLList, (struct Node *) &CDXLNodes[ i ] );
  687.         CDXLNodes[ i ].Buffer    = FrameBuffer[ i ];
  688.         CDXLNodes[ i ].Length    = FirstPan.Size;
  689.         CDXLNodes[ i ].DoneFunc    = CDXLIntrCode;
  690.         }
  691.  
  692.     // Tie list together to give us endless loop
  693.     CDXLList.mlh_Head->mln_Pred     = CDXLList.mlh_TailPred;
  694.     CDXLList.mlh_TailPred->mln_Succ = CDXLList.mlh_Head;
  695.  
  696.     // Signal used when frame is ready
  697.     if ( ( SwitchSignalBit = AllocSignal( -1 ) ) == -1 )
  698.         Error( "Cannot get signals" );
  699.  
  700.     SwitchSignal = ( 1 << SwitchSignalBit );
  701.  
  702.     // setup for CDXLIntrCode
  703.     OurTask = FindTask( NULL );
  704.     }
  705.  
  706.  
  707. /***********************************************************************
  708. ***
  709. ***  InitViewInfo
  710. ***
  711. ************************************************************************/
  712.  
  713. void InitViewInfo(
  714.     void
  715.     )
  716.     {
  717.     LONG File;
  718.     SHORT i;
  719.  
  720.     // Setup views
  721.     if ( ! ( File = Open( CDXLFile, MODE_OLDFILE ) ) )
  722.         Error( "CDXL file not available" );
  723.  
  724.     for ( i = 0; i < MaxNodes; i++ )
  725.         SetViewInfo( File, &FirstPan, i );
  726.  
  727.     Close( File );
  728.     }
  729.  
  730.  
  731. /***********************************************************************
  732. ***
  733. ***  Quit
  734. ***
  735. ***********************************************************************/
  736.  
  737. void Quit(
  738.     LONG Code
  739.     )
  740.     {
  741.     static SHORT Quitting = FALSE;
  742.  
  743.     if ( Quitting )
  744.         return;
  745.  
  746.     Quitting = TRUE;
  747.  
  748.     if ( IntuitionBase )
  749.         RemakeDisplay();
  750.  
  751.     QuitViewInfo();
  752.  
  753.     QuitAudio();
  754.  
  755.     QuitCDXL();
  756.  
  757.     QuitCDTV();
  758.  
  759.     if ( IntuitionBase )
  760.         CloseLibrary( (struct Library *) IntuitionBase );
  761.  
  762.     if ( GfxBase )
  763.         CloseLibrary( (struct Library *) GfxBase );
  764.  
  765.     if ( Code )
  766.         printf( "\n%s quit! (code %d)\n", Program, Code );
  767.  
  768.     exit( Code );
  769.     }
  770.  
  771.  
  772. /***********************************************************************
  773. ***
  774. ***  QuitAudio
  775. ***
  776. ************************************************************************/
  777.  
  778. void QuitAudio(
  779.     void
  780.     )
  781.     {
  782.     if ( AudioHandlerInUse )
  783.         {
  784.         StopAudio();
  785.         SetIntVector( INTB_AUD0, OldAudioVector );
  786.         }
  787.  
  788.     if ( AudioMain.ioa_Request.io_Device )
  789.         {
  790.         AudioMain.ioa_Request.io_Command = ADCMD_FREE;
  791.         DoIO( (struct IORequest *) &AudioMain );
  792.  
  793.         CloseDevice( (struct IORequest *) &AudioMain );
  794.  
  795.         if ( AudioMainPort )
  796.             DeletePort( AudioMainPort );
  797.         }
  798.     }
  799.  
  800.  
  801. /***********************************************************************
  802. ***
  803. ***  QuitCDTV
  804. ***
  805. ************************************************************************/
  806.  
  807. void QuitCDTV(
  808.     void
  809.     )
  810.     {
  811.     if ( CDTVIOReq )
  812.         {
  813.         if ( CDTVIOReq->io_Device )
  814.             CloseDevice( (struct IORequest *) CDTVIOReq );
  815.  
  816.         DeleteStdIO( CDTVIOReq );
  817.         }
  818.  
  819.     if ( CDTVIOPort )
  820.         DeletePort( CDTVIOPort );
  821.     }
  822.  
  823.  
  824. /***********************************************************************
  825. ***
  826. ***  QuitCDXL
  827. ***
  828. ************************************************************************/
  829.  
  830. void QuitCDXL(
  831.     void
  832.     )
  833.     {
  834.     SHORT i;
  835.  
  836.     if ( SwitchSignalBit != -1 )
  837.         FreeSignal( SwitchSignalBit );
  838.  
  839.     for ( i = 0; i < MaxNodes; i++ )
  840.         if ( FrameBuffer[ i ] )
  841.             FreeMem( FrameBuffer[ i ], FirstPan.Size );
  842.     }
  843.  
  844.  
  845. /***********************************************************************
  846. ***
  847. ***  QuitViewInfo
  848. ***
  849. ************************************************************************/
  850.  
  851. void QuitViewInfo(
  852.     void
  853.     )
  854.     {
  855.     SHORT i;
  856.  
  857.     for ( i = 0; i < MaxNodes; i++ )
  858.         {
  859.         if ( Copper[ i ] )
  860.             FreeMem( Copper[ i ], COPPER_BUFFER_SIZE );
  861.  
  862.         FreeVPortCopLists( &CDXLVP[ i ] );
  863.  
  864.         if ( CDXLVP[ i ].ColorMap )
  865.             FreeColorMap( CDXLVP[ i ].ColorMap );
  866.  
  867.         if ( CDXLView[ i ].LOFCprList )
  868.             FreeCprList( CDXLView[ i ].LOFCprList );
  869.  
  870.         if ( CDXLView[ i ].SHFCprList )
  871.             FreeCprList( CDXLView[ i ].SHFCprList );
  872.         }
  873.     }
  874.  
  875.  
  876. /***********************************************************************
  877. ***
  878. ***  SetViewInfo
  879. ***
  880. ***    Somebody tell me a better way of centering a view, overscan or
  881. ***    not...
  882. ***
  883. ************************************************************************/
  884.  
  885. void SetViewInfo(
  886.     LONG File,
  887.     PAN *Pan,
  888.     ULONG Num
  889.     )
  890.     {
  891.     struct View *CurrentView;
  892.     UBYTE *Buffer;
  893.     LONG PlaneSize;
  894.     LONG i;
  895.     SHORT OriginCenterX;
  896.     SHORT OriginCenterY;
  897.     SHORT VP_X;
  898.     SHORT VP_Y;
  899.     SHORT NewX;
  900.     SHORT NewY;
  901.     SHORT GoHiRes = FALSE;
  902.     SHORT GoLace  = FALSE;
  903.  
  904.     // Init structures
  905.     InitView( &CDXLView[ Num ] );
  906.     InitVPort( &CDXLVP[ Num ] );
  907.  
  908.     if ( ! ( CDXLVP[ Num ].ColorMap = GetColorMap( 64 ) ) )
  909.         Error( "Not enough memory for ColorMap" );
  910.  
  911.     if ( ! ( Copper[ Num ] = AllocMem( COPPER_BUFFER_SIZE, MEMF_CHIP ) ) )
  912.         Error( "Not enough memory for Copper Lists" );
  913.  
  914.     // Pre-Fill Buffers
  915.     if ( Read( File, FrameBuffer[ Num ], Pan->Size ) != Pan->Size )
  916.         Error( "Not a CDXL file" );
  917.  
  918.     // InterLace and High Resolution guesses
  919.     if ( Pan->XSize >= 640 )
  920.         GoHiRes = TRUE;
  921.  
  922.     if ( Pan->YSize >= 400 )
  923.         GoLace = TRUE;
  924.  
  925.     CDXLView[ Num ].ViewPort = &CDXLVP[ Num ];
  926.  
  927.     // Choose mode
  928.     CDXLView[ Num ].Modes = 0;
  929.     switch ( PI_VIDEO( Pan ) )
  930.         {
  931.         case ( PIV_HAM ):
  932.             CDXLView[ Num ].Modes = HAM;
  933.             break;
  934.  
  935.         case ( PIV_YUV ):
  936.             Error( "Cannot handle YUV video" );
  937.             break;
  938.  
  939.         case ( PIV_AVM ):
  940.             GoHiRes = TRUE;
  941.             break;
  942.  
  943.         case ( PIV_STANDARD ):
  944.             if ( Pan->PixelSize == 6 )
  945.                 CDXLView[ Num ].Modes = EXTRA_HALFBRITE;
  946.             break;
  947.  
  948.         default:
  949.             Error( "Unknown PAN Info" );
  950.             break;
  951.         }
  952.  
  953.     if ( GoLace )
  954.         CDXLView[ Num ].Modes |= LACE;
  955.  
  956.     CDXLVP[ Num ].Modes = CDXLView[ Num ].Modes;
  957.  
  958.     // NOTE: The view does not care about HIRES
  959.     if ( GoHiRes )
  960.         CDXLVP[ Num ].Modes |= HIRES;
  961.  
  962.     CDXLVP[ Num ].DWidth   = Pan->XSize;
  963.     CDXLVP[ Num ].DHeight  = Pan->YSize;
  964.     CDXLVP[ Num ].RasInfo  = &CDXLRI[ Num ];
  965.     CDXLRI[ Num ].RxOffset = 0;
  966.     CDXLRI[ Num ].RyOffset = 0;
  967.     CDXLRI[ Num ].Next     = 0;
  968.  
  969.     // Center images (use view and viewport to center small images)
  970.     // Remember:
  971.     //    CurrentView->DxOffset & OriginCenterX are lo-res
  972.     //    CurrentView->DyOffset & OriginCenterY are non-interlace
  973.     //    Views are lo-res specifications ONLY!
  974.     //    ViewPorts may be lo-res or hi-res
  975.     CurrentView    = ViewAddress();
  976.     OriginCenterX    = ( CurrentView->ViewPort->DWidth  >> ( ( CurrentView->ViewPort->Modes & HIRES ) ? 2 : 1 ) );
  977.     OriginCenterY    = ( CurrentView->ViewPort->DHeight >> ( ( CurrentView->ViewPort->Modes & LACE  ) ? 2 : 1 ) );
  978.  
  979.     NewX = ( CurrentView->DxOffset + OriginCenterX - ( Pan->XSize >> ( ( GoHiRes ) ? 2 : 1 ) ) );
  980.     NewY = ( CurrentView->DyOffset + OriginCenterY - ( Pan->YSize >> ( ( GoLace  ) ? 2 : 1 ) ) );
  981.  
  982.     // Check Min for View
  983.     if ( NewX < 98 )
  984.         NewX = 98;
  985.  
  986.     if ( NewY < 25 )
  987.         NewY = 25;
  988.  
  989.     // Check Max for View
  990.     if ( NewX > 129 )
  991.         {
  992.         VP_X = ( NewX - 129 );
  993.         NewX = 129;
  994.         }
  995.     else
  996.         VP_X = 0;
  997.  
  998.     if ( NewY > 56 )
  999.         {
  1000.         VP_Y = ( NewY - 56 );
  1001.         NewY = 56;
  1002.         }
  1003.     else
  1004.         VP_Y = 0;
  1005.  
  1006.     CDXLView[ Num ].DxOffset = NewX;
  1007.     CDXLView[ Num ].DyOffset = NewY;
  1008.     CDXLVP[ Num ].DxOffset   = ( VP_X << ( ( GoHiRes ) ? 1 : 0 ) );
  1009.     CDXLVP[ Num ].DyOffset   = VP_Y;
  1010.  
  1011.     // Set Bit Plane Ptr's, handle interleaved (for display)
  1012.     Buffer = ( FrameBuffer[ Num ] + PAN_SIZE + CMAP_SIZE( Pan ) );
  1013.     InitBitMap( &CDXLBM[ Num ], Pan->PixelSize, Pan->XSize, Pan->YSize );
  1014.  
  1015.     if ( PI_PIXEL( Pan ) == PIF_LINES )
  1016.         {
  1017.         PlaneSize = CDXLBM[ Num ].BytesPerRow;
  1018.  
  1019.         CDXLBM[ Num ].BytesPerRow *= Pan->PixelSize;
  1020.         }
  1021.     else
  1022.         PlaneSize = ( CDXLBM[ Num ].BytesPerRow * Pan->YSize );
  1023.  
  1024.     for ( i = 0; i < Pan->PixelSize; i++ )
  1025.         CDXLBM[ Num ].Planes[ i ] = &Buffer[ ( i * PlaneSize ) ];
  1026.  
  1027.     // Make View
  1028.     LoadRGB4( &CDXLVP[ Num ], FrameCMap[ Num ], CMAP_SIZE( Pan ) );
  1029.     CDXLRI[ Num ].BitMap = &CDXLBM[ Num ];
  1030.     MakeVPort( &CDXLView[ Num ], &CDXLVP[ Num ] );
  1031.     MrgCop( &CDXLView[ Num ] );
  1032.     LoadView( &CDXLView[ Num ] );
  1033.  
  1034.     Color[ Num ] = CopyCopper( Copper[ Num ] );
  1035.     }
  1036.  
  1037.  
  1038. /***********************************************************************
  1039. ***
  1040. ***  StartAudio
  1041. ***
  1042. ***    Start interrupts for switching audio buffers
  1043. ***    Set Ptr and Length
  1044. ***
  1045. ************************************************************************/
  1046.  
  1047. void StartAudio(
  1048.     void
  1049.     )
  1050.     {
  1051.     CLEAR_INTR( INTF_AUD0 );
  1052.     ENABLE_DMA( DMAF_AUD0 );
  1053.     ENABLE_DMA( DMAF_AUD1 );
  1054.     ENABLE_INTR( INTF_AUD0 );
  1055.     }
  1056.  
  1057.  
  1058. /***********************************************************************
  1059. ***
  1060. ***  StopAudio
  1061. ***
  1062. ************************************************************************/
  1063.  
  1064. void StopAudio(
  1065.     void
  1066.     )
  1067.     {
  1068.     DISABLE_DMA( DMAF_AUD0 );
  1069.     DISABLE_DMA( DMAF_AUD1 );
  1070.     DISABLE_INTR( INTF_AUD0 );
  1071.     CLEAR_INTR( INTF_AUD0 );
  1072.     }
  1073.